﻿using BCCommon;
using BCCommon.Enums;
using BCCommon.Exceptions;
using BCCommon.OAEnums;
using BCCommon.OAEnums.Workflow;
using BCData.Common.Dictionary;
using BCData.OA.ApplyOrder;
using BCData.OA.Reimbursement;
using BCData.OA.TeamWorks.TaskReceiverRecord;
using BCData.OA.TeamWorks.TaskRecord;
using BCData.OA.TeamWorks.TaskRejectRecord;
using BCData.OA.TeamWorks.TaskRejectReplyRecord;
using BCData.OA.Workflow.WorkflowActivityInstanceBusiness;
using BCData.OA.Workflow.WorkflowActivityInstanceReference;
using BCDto.OA.Common;
using BCDto.OA.TeamWorks.TaskRecord;
using BCDto.OA.TeamWorks.TaskRejectRecord;
using BCDto.OA.TeamWorks.TaskRejectReplyRecord;
using BCDto.OA.Workflow.WorkflowActivityInstance;
using BCDto.OA.Workflow.WorkflowActivityInstanceRecord;
using BCDto.OA.Workflow.WorkflowActivityStepInstance;
using BCEntity.Common.Dictionary;
using BCEntity.OA.TeamWorks.TaskRecord;
using BCEntity.OA.Workflow.WorkflowActivityInstance;
using BCService.OA.TeamWorks.TaskResourceRecord;
using BCService.OA.Workflow.WorkflowActivityInstanceBusiness;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;

namespace BCService.OA.TeamWorks.TaskRecordService
{
    /// <summary>
    /// 工作流任务记录。
    /// </summary>
    public class TaskRecordService : ITaskRecordService
    {
        private readonly IApplicationContextService applicationContextService;
        //private readonly IGeneralWorkflowService generalWorkflowService;
        private readonly ITaskRecordData taskRecordData;
        //private readonly IFMISTaskRecordData fMISTaskRecordData;
        private readonly IWorkflowActivityInstanceBusinessService workflowActivityInstanceBusinessService;
        private readonly IApplyOrderData applyOrderData;
        private readonly ITaskRejectRecordData taskRejectRecordData;
        private readonly ITaskRejectReplyRecordData taskRejectReplyRecordData;
        //private readonly IPaymentReceiptCallbackData paymentReceiptCallbackData;
        //private readonly IAccountCertificateTemplateData accountCertificateTemplateData;
        private readonly IReimbursementRecordData reimbursementRecordData;
        private readonly IWorkflowActivityInstanceBusinessData workflowActivityInstanceBusinessData;
        private readonly IDictionaryReferenceData dictionaryReferenceData;
        private readonly ITaskResourceRecordService taskResourceRecordService;
        private readonly ITaskReceiverRecordData taskReceiverRecordData;
        private readonly IWorkflowActivityInstanceReferenceData workflowActivityInstanceReferenceData;
        private readonly IDatabaseContext databaseContext;

        public TaskRecordService(IApplicationContextService applicationContextService,
            //IGeneralWorkflowService generalWorkflowService,
            ITaskRecordData taskRecordData,
            IWorkflowActivityInstanceBusinessService workflowActivityInstanceBusinessService,
            IApplyOrderData applyOrderData,
            //IFMISTaskRecordData fMISTaskRecordData,
            ITaskRejectRecordData taskRejectRecordData,
            ITaskRejectReplyRecordData taskRejectReplyRecordData,
            //IPaymentReceiptCallbackData paymentReceiptCallbackData,
            //IAccountCertificateTemplateData accountCertificateTemplateData,
            IReimbursementRecordData reimbursementRecordData,
            IWorkflowActivityInstanceBusinessData workflowActivityInstanceBusinessData,
            IDictionaryReferenceData dictionaryReferenceData,
            ITaskResourceRecordService taskResourceRecordService,
            ITaskReceiverRecordData taskReceiverRecordData,
            IWorkflowActivityInstanceReferenceData workflowActivityInstanceReferenceData,
            IDatabaseContext databaseContext)
        {
            this.applicationContextService = applicationContextService;
            //this.generalWorkflowService = generalWorkflowService;
            this.taskRecordData = taskRecordData;
            this.workflowActivityInstanceBusinessService = workflowActivityInstanceBusinessService;
            this.applyOrderData = applyOrderData;
            //this.fMISTaskRecordData = fMISTaskRecordData;
            this.taskRejectRecordData = taskRejectRecordData;
            this.taskRejectReplyRecordData = taskRejectReplyRecordData;
            //this.paymentReceiptCallbackData = paymentReceiptCallbackData;
            //this.accountCertificateTemplateData = accountCertificateTemplateData;
            this.reimbursementRecordData = reimbursementRecordData;
            this.workflowActivityInstanceBusinessData = workflowActivityInstanceBusinessData;
            this.dictionaryReferenceData = dictionaryReferenceData;
            this.taskResourceRecordService = taskResourceRecordService;
            this.taskReceiverRecordData = taskReceiverRecordData;
            this.workflowActivityInstanceReferenceData = workflowActivityInstanceReferenceData;
            this.databaseContext = databaseContext;
        }

        private IEnumerable<TaskRecordDto> GetTaskRecords(long workflowActivityInstanceId)
        {
            IEnumerable<TaskRecordEntity> taskrecordEntities = this.taskRecordData.GetByWorkflowActivityInstanceIdAsync(workflowActivityInstanceId).GetAwaiter().GetResult();
            List<TaskRecordDto> result = new List<TaskRecordDto>();
            foreach (var item in taskrecordEntities)
            {
                TaskRecordDto taskRecord = item.As<TaskRecordDto>();
                taskRecord.Applicant = taskRecord.TaskExecuterFullName;
                var nameList = taskRecordData.GetByWorkflowActivityInstanceIdAsync(taskRecord.WorkflowActivityInstanceId).GetAwaiter().GetResult().ToList();
                if (nameList.Any())
                {
                    var names = nameList.Where(s => s.CurrentlyStep > 0).OrderBy(s => s.CurrentlyStep).Select(s => s.TaskExecuterFullName).Distinct();
                    taskRecord.Approvers = names.Any() ? string.Join(",", names) : string.Empty;
                }
                else
                {
                    taskRecord.Approvers = taskRecord.TaskExecuterFullName;
                }
                var tempTasks = taskRecordData.GetByWorkflowActivityInstanceIdAsync(taskRecord.WorkflowActivityInstanceId, 0).GetAwaiter().GetResult();
                taskRecord.Applicant = tempTasks.Any() ? tempTasks.First().TaskExecuterFullName : string.Empty;
                result.Add(taskRecord);
            }
            return result.OrderBy(p => p.CreateTime).ToList();
        }

        private IEnumerable<TaskRejectRecordDto> GetTaskRejectRecords(long workflowActivityInstanceId)
        {
            var rejectReocrds = this.taskRejectRecordData.GetListByWorkflowActivityInstanceId(workflowActivityInstanceId).GetAwaiter().GetResult();
            List<TaskRejectRecordDto> result = new List<TaskRejectRecordDto>();
            foreach (var item in rejectReocrds)
            {
                var dto = item.As<TaskRejectRecordDto>();

                dto.Replys = this.taskRejectReplyRecordData.GetEntities(item.WorkflowActivityInstanceId, item.TaskRejectRecordId).GetAwaiter().GetResult().As<List<TaskRejectReplyRecordDto>>();

                result.Add(dto);
            }
            return result.OrderBy(p => p.CreateTime).ToList();
        }

        /// <summary>
        /// 获取指定的任务单记录信息
        /// </summary>
        /// <param name="taskRecordNo">任务单编号</param>
        /// <returns></returns>
        public TaskRecordViewDto GetDetailEntity(string taskRecordNo)
        {
            var task = this.taskRecordData.GetEntity(taskRecordNo).GetAwaiter().GetResult();
            if (task == null)
                return new TaskRecordViewDto();
            TaskRecordViewDto viewDto = task.As<TaskRecordViewDto>();
            var referenceEntity = this.workflowActivityInstanceBusinessService.GetActivityInstanceReference(task.WorkflowActivityInstanceId);
            //switch (task.BusinessType.As<OATaskBusinessType>())
            //{
            //    #region OA
            //    case OATaskBusinessType.WorkflowBusiness_Reimbursement_Sale:
            //        viewDto.OAApplyOrder = this.applyOrderData.GetByApplyOrderNoAsync(referenceEntity.ReferenceNo).GetAwaiter().GetResult().As<ApplyOrderDto>();
            //        if (viewDto.OAApplyOrder != null)
            //        {
            //            var reimbursementRecord = reimbursementRecordData.GetEntityByApplyCode(viewDto.OAApplyOrder.ApplyCode).GetAwaiter().GetResult();
            //            viewDto.VehicleSaleContractNo = reimbursementRecord?.VehicleSaleContractNo;
            //        }
            //        break;
            //    case OATaskBusinessType.WorkflowBusiness_RemedyCheckIn_Operations:
            //    case OATaskBusinessType.WorkflowBusiness_Reimbursement_Normal:
            //        viewDto.OAApplyOrder = this.applyOrderData.GetByApplyOrderNoAsync(referenceEntity.ReferenceNo).GetAwaiter().GetResult().As<ApplyOrderDto>();
            //        break;
            //    #endregion

            //    #region 入账
            //    case OATaskBusinessType.WorkflowBusiness_AccountCertificate_Purchase:
            //        var accountCertificateTemplatePurchase = accountCertificateTemplateData.GetAccountCertificateEntity(referenceEntity.ReferenceNo).GetAwaiter().GetResult();
            //        viewDto.VehiclePurchaseContractNo = accountCertificateTemplatePurchase != null ? accountCertificateTemplatePurchase.ReferenceNo : string.Empty;
            //        break;
            //    case OATaskBusinessType.WorkflowBusiness_AccountCertificate_Sale:
            //        var accountCertificateTemplateSale = accountCertificateTemplateData.GetAccountCertificateEntity(referenceEntity.ReferenceNo).GetAwaiter().GetResult();
            //        viewDto.VehicleSaleContractNo = accountCertificateTemplateSale != null ? accountCertificateTemplateSale.ReferenceNo : string.Empty;
            //        break;
            //    #endregion

            //    #region 收付款
            //    case OATaskBusinessType.WorkflowBusiness_DepositPayment_Purchase:
            //    case OATaskBusinessType.WorkflowBusiness_LastPayment_Purchase:
            //        var paymentReceiptPurchase = paymentReceiptCallbackData.GetPaymentReceiptCallbackByPaymentReceiptCertificateNoAsync(referenceEntity.ReferenceNo).GetAwaiter().GetResult();
            //        viewDto.VehiclePurchaseContractNo = paymentReceiptPurchase?.CallbackNo;
            //        break;
            //    case OATaskBusinessType.WorkflowBusiness_DepositReceipt_Sale:
            //    case OATaskBusinessType.WorkflowBusiness_LastPaymentReceipt_Sale:
            //    case OATaskBusinessType.WorkflowBusiness_SettlementPayment_Sale:
            //    case OATaskBusinessType.WorkflowBusiness_PeriodizationReceipt_Loan:
            //    case OATaskBusinessType.WorkflowBusiness_DownPaymentReceipt_Sale:
            //    case OATaskBusinessType.WorkflowBusiness_LateFeeReceipt_Sale:
            //        var paymentReceiptSaleCallback = paymentReceiptCallbackData.GetPaymentReceiptCallbackByPaymentReceiptCertificateNoAsync(referenceEntity.ReferenceNo).GetAwaiter().GetResult();
            //        viewDto.VehicleSaleContractNo = paymentReceiptSaleCallback?.CallbackNo;
            //        break;
            //    #endregion

            //    #region 报销付款
            //    case OATaskBusinessType.WorkflowBusiness_Payment_Reimbursement:
            //        var paymentReceiptReimbursement = paymentReceiptCallbackData.GetPaymentReceiptCallbackByPaymentReceiptCertificateNoAsync(referenceEntity.ReferenceNo).GetAwaiter().GetResult();
            //        if (paymentReceiptReimbursement != null)
            //        {
            //            viewDto.OAApplyOrder = this.applyOrderData.GetByApplyOrderNoAsync(paymentReceiptReimbursement.CallbackNo).GetAwaiter().GetResult().As<ApplyOrderDto>();
            //        }
            //        break;
            //    #endregion
            //    default:
            //        break;
            //}
            if (viewDto.OAApplyOrder != null && viewDto.OAApplyOrder.CopierIds.Length > 0)
            {
                viewDto.OAApplyOrder.Copiers = taskReceiverRecordData.GetByWorkflowActivityInstanceId(task.WorkflowActivityInstanceId).GetAwaiter().GetResult().As<List<TaskReceiverRecordDto>>();
            }
            //var taskRecords = this.taskRecordData.GetByWorkflowActivityInstanceIdAsync(task.WorkflowActivityInstanceId).GetAwaiter().GetResult().As<List<TaskRecordDto>>();
            //if (taskRecords.Any())
            //{
            //    taskRecords = taskRecords.Where(s => s.CurrentlyStep != 0).OrderBy(s => s.CurrentlyStep).ToList();

            //    var list = (from data in taskRecords
            //                group data by data.CurrentlyStep into g
            //                select new TaskRecordApproverViewDto
            //                {
            //                    CurrentlyStep = g.Key.Value,
            //                    TaskRecordNo = g.OrderByDescending(p => p.CompleteTime).First().TaskRecordNo,
            //                    WorkflowActivityInstanceId = g.OrderByDescending(p => p.CompleteTime).First().WorkflowActivityInstanceId,
            //                    LastApproverId = g.OrderByDescending(p => p.CompleteTime).First().TaskExecuterAdminId,
            //                    LastApproverName = g.OrderByDescending(p => p.CompleteTime).First().TaskExecuterFullName,
            //                    LastApproverTime = g.OrderByDescending(p => p.CompleteTime).First().CompleteTime,
            //                    LastApproverStatus = g.OrderByDescending(p => p.CompleteTime).First().HandleStatus,
            //                }).ToList();
            //    foreach (var groupTask in list)
            //    {
            //        groupTask.RejectList = taskRejectRecordData.GetListByWorkflowActivityInstanceId(groupTask.WorkflowActivityInstanceId, groupTask.TaskRecordNo).GetAwaiter().GetResult().OrderBy(c => c.CreateTime).As<List<TaskRejectRecordDto>>();
            //        foreach (var reject in groupTask.RejectList)
            //        {
            //            reject.Replys = taskRejectReplyRecordData.GetEntities(reject.WorkflowActivityInstanceId, reject.TaskRejectRecordId).GetAwaiter().GetResult().As<List<TaskRejectReplyRecordDto>>();
            //        }
            //    }
            //    viewDto.ApproverList = list.ToList();
            //}  
            var workflowActivityInstanceDto = this.workflowActivityInstanceBusinessData.GetEntity(task.WorkflowActivityInstanceId).GetAwaiter().GetResult().As<WorkflowActivityInstanceDto>();
            WorkflowActivityInstanceRecordDto workflowActivityInstanceRecordDto = workflowActivityInstanceDto.As<WorkflowActivityInstanceRecordDto>();
            workflowActivityInstanceRecordDto.TaskRecords = this.GetTaskRecords(task.WorkflowActivityInstanceId).ToList();
            workflowActivityInstanceRecordDto.TaskRejectRecords = this.GetTaskRejectRecords(task.WorkflowActivityInstanceId).ToList();
            workflowActivityInstanceRecordDto.TaskResourceRecords = this.taskResourceRecordService.GetList(task.WorkflowActivityInstanceId).ToList();
            viewDto.WorkflowActivityInstanceRecord = workflowActivityInstanceRecordDto;
            return viewDto;
        }

        /// <summary>
        /// 分页获取当前人员下的任务列表
        /// </summary>
        /// <param name="executerAdminId">执行人Id</param>
        /// <param name="start">开始日期</param>
        /// <param name="end">结束日期</param>
        /// <param name="handleStatus">处理状态</param>
        /// <param name="sortName">排序字段</param>
        /// <param name="companyId">公司Id</param>
        /// <param name="ascending">是否升序排序</param>
        /// <param name="pageIndex">分页页码</param>
        /// <param name="pageSize">分页页数</param>
        /// <param name="taskStep">任务步骤</param>
        /// <param name="isMyApproved">是否我审批</param>
        /// <returns></returns>
        public PageableList<TaskRecordDto> Query(long? executerAdminId, DateTime? start, DateTime? end, OATaskHandleStatus? handleStatus, string sortName, int? companyId, bool? ascending, int pageIndex, int pageSize, int? taskStep = null, bool? isMyApproved = null)
        {
            var (taskRecords, count) = this.taskRecordData.Query(executerAdminId, start, end, handleStatus, sortName.ToCamelCase(), companyId, ascending, pageIndex, pageSize, taskStep, isMyApproved).GetAwaiter().GetResult();
            List<TaskRecordDto> list = new List<TaskRecordDto>();

            foreach (var item in taskRecords)
            {
                TaskRecordDto taskRecord = item.As<TaskRecordDto>();
                taskRecord.Applicant = taskRecord.TaskExecuterFullName;
                var nameList = taskRecordData.GetByWorkflowActivityInstanceIdAsync(taskRecord.WorkflowActivityInstanceId).GetAwaiter().GetResult().ToList();
                if (nameList.Any())
                {
                    var names = nameList.Where(s => s.CurrentlyStep > 0).OrderBy(s => s.CurrentlyStep).Select(s => s.TaskExecuterFullName).Distinct();
                    taskRecord.Approvers = names.Any() ? string.Join(",", names) : string.Empty;
                }
                else
                {
                    taskRecord.Approvers = taskRecord.TaskExecuterFullName;
                }
                var tempTasks = taskRecordData.GetByWorkflowActivityInstanceIdAsync(taskRecord.WorkflowActivityInstanceId, 0).GetAwaiter().GetResult();
                taskRecord.Applicant = tempTasks.Any() ? tempTasks.First().TaskExecuterFullName : string.Empty;
                list.Add(taskRecord);
            }

            return new PageableList<TaskRecordDto>()
            {
                Items = list,
                Count = count
            };
        }

        public bool UpdateHandleStatus(string taskRecordNo, OATaskHandleStatus handleStatus)
        {
            if (!this.taskRecordData.CheckExists(taskRecordNo).GetAwaiter().GetResult())
            {
                throw new ArgumentException("此任务不存在");
            }
            return this.taskRecordData.UpdateHandleStatus(taskRecordNo, handleStatus).GetAwaiter().GetResult();
        }

        /// <summary>
        /// 获取指定的任务单信息
        /// </summary>
        /// <param name="taskRecordNo">任务单编号</param>
        /// <returns></returns>
        public TaskRecordDto GetEntity(string taskRecordNo)
        {
            return taskRecordData.GetEntity(taskRecordNo).GetAwaiter().GetResult().As<TaskRecordDto>();
        }

        /// <summary>
        /// 获取驳回信息列表
        /// </summary>
        /// <param name="executerAdminId"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="sortName"></param>
        /// <param name="companyId"></param>
        /// <param name="ascending"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public PageableList<TaskRejectRecordViewDto> GetRejectRecords(long? executerAdminId, DateTime? start, DateTime? end, string sortName, int companyId, bool? ascending, int pageIndex, int pageSize)
        {
            var (list, count) = this.taskRejectRecordData.GetListRejectRecordsAsync(executerAdminId, start, end, sortName.ToCamelCase(), ascending, pageIndex, pageSize, companyId).GetAwaiter().GetResult();

            return new PageableList<TaskRejectRecordViewDto>
            {
                Count = count,
                Items = list.As<List<TaskRejectRecordViewDto>>()
            };
        }

        /// <summary>
        /// 处理有被驳回的任务为完成
        /// </summary>
        /// <param name="taskRecordNo"></param>
        /// <returns></returns>
        public bool HandleHasRejectedRecord(string taskRecordNo)
        {
            bool result = false;
            var currentTask = this.GetEntity(taskRecordNo);
            if (currentTask == null)
            {
                throw new ArgumentException("此任务不存在");
            }
            var fmisTaskRecords = this.taskRecordData.Get(currentTask.WorkflowActivityInstanceId).GetAwaiter().GetResult();
            var instanceDto = this.workflowActivityInstanceBusinessData.GetEntity(currentTask.WorkflowActivityInstanceId).GetAwaiter().GetResult().As<WorkflowActivityInstanceDto>();
            if (fmisTaskRecords.Any())
            {
                this.workflowActivityInstanceBusinessData.UpdateWorkflowActivityCurrentlyStepNext(instanceDto.WorkflowActivityInstanceId).GetAwaiter().GetResult();
                //说明有驳回过
                if (fmisTaskRecords.Any(s => s.CurrentlyStep == instanceDto.CurrentlyStep + 1 && s.HandleStatus == OATaskHandleStatus.Dismissed))
                {
                    var taskRecordEntity = this.MakeTask(instanceDto, instanceDto.CurrentlyStep + 1);
                    var nextTaskRecordEntity = fmisTaskRecords.OrderByDescending(p => p.CreateTime).First(p => p.CurrentlyStep == instanceDto.CurrentlyStep + 1 && p.TaskExecuterAdminId.HasValue);
                    taskRecordEntity.TaskExecuterAdminId = nextTaskRecordEntity.TaskExecuterAdminId;
                    taskRecordEntity.TaskExecuterFullName = nextTaskRecordEntity.TaskExecuterFullName;
                    taskRecordEntity.StartTime = DateTime.Now;
                    //if (!this.taskRecordData.UpdateStartTime(taskRecordEntity).GetAwaiter().GetResult())
                    //{
                    //    throw new ArgumentException(string.Format("更新任务执行人时失败,任务编号:{0}", taskRecordEntity.TaskRecordId));
                    //}
                    this.taskRecordData.UpdateHandleStatus(currentTask.TaskRecordNo, OATaskHandleStatus.Handled).GetAwaiter().GetResult();
                }
                else
                {

                }
                result = true;
            }
            else
            {
                this.workflowActivityInstanceBusinessData.UpdateWorkflowActivityCurrentlyStepNext(instanceDto.WorkflowActivityInstanceId).GetAwaiter().GetResult();
                var taskRecords = this.taskRecordData.GetByWorkflowActivityInstanceIdAsync(currentTask.WorkflowActivityInstanceId).GetAwaiter().GetResult();
                if (taskRecords.Any(s => s.CurrentlyStep == instanceDto.CurrentlyStep + 1 && s.HandleStatus == OATaskHandleStatus.Dismissed))
                {
                    var taskRecordEntity = this.MakeTask(instanceDto, instanceDto.CurrentlyStep + 1);
                    var nextTaskRecordEntity = taskRecords.OrderByDescending(p => p.CreateTime).First(p => p.CurrentlyStep == instanceDto.CurrentlyStep + 1 && p.TaskExecuterAdminId.HasValue);
                    taskRecordEntity.TaskExecuterAdminId = nextTaskRecordEntity.TaskExecuterAdminId;
                    taskRecordEntity.TaskExecuterFullName = nextTaskRecordEntity.TaskExecuterFullName;
                    taskRecordEntity.StartTime = DateTime.Now;
                    //if (!this.fMISTaskRecordData.UpdateStartTime(taskRecordEntity).GetAwaiter().GetResult())
                    //{
                    //    throw new ArgumentException(string.Format("更新任务执行人时失败,任务编号:{0}", taskRecordEntity.TaskRecordId));
                    //}
                    this.taskRecordData.UpdateHandleStatus(currentTask.TaskRecordNo, OATaskHandleStatus.Handled).GetAwaiter().GetResult();
                    this.workflowActivityInstanceBusinessData.UpdateWorkflowActivityCurrentlyStepNext(instanceDto.WorkflowActivityInstanceId).GetAwaiter().GetResult();
                }
                else
                {
                    // this.workflowRunningService.Assigning(instanceDto.WorkflowActivityId);
                }
                result = true;
            }
            return result;
        }

        #region 构建步骤任务
        /// <summary>
        /// 
        /// </summary>
        /// <param name="instanceDto"></param>
        /// <param name="currentlyStep"></param>
        /// <returns></returns>
        public TaskRecordEntity MakeTask(WorkflowActivityInstanceDto instanceDto, int currentlyStep)
        {
            var taskRecordEntities = this.taskRecordData.Get(instanceDto.WorkflowActivityInstanceId).GetAwaiter().GetResult();
            var taskRecords = taskRecordEntities.OrderByDescending(p => p.CreateTime);
            if (taskRecords.First().TaskExecuterAdminId.HasValue)
            {
                TaskRecordEntity taskRecordEntity = null;
                if (taskRecords.Any(p => p.CurrentlyStep == currentlyStep))
                {
                    taskRecordEntity = taskRecords.First(p => p.CurrentlyStep == currentlyStep);
                }
                else if (taskRecords.Count() == 1)
                {
                    taskRecordEntity = taskRecords.First();
                    taskRecordEntity.CurrentlyStep = currentlyStep;
                }
                else
                {
                    taskRecordEntity = taskRecords.First(p => p.CurrentlyStep == instanceDto.CurrentlyStep - 1);
                    taskRecordEntity.CurrentlyStep = currentlyStep;
                }
                this.AddTaskRecord(taskRecordEntity, true);
                return this.taskRecordData.GetLatestRecordAsync(instanceDto.WorkflowActivityInstanceId).GetAwaiter().GetResult();
            }
            else
            {
                return taskRecords.First();
            }
        }

        /// <summary>
        /// 添加任务记录
        /// </summary>
        /// <param name="entity">任务信息</param>
        /// <param name="isAppend">是否仅追加基本任务记录</param>
        private void AddTaskRecord(TaskRecordEntity entity, bool isAppend)
        {
            DictionaryReferenceEntity dictionaryReferenceEntity = this.dictionaryReferenceData.GetEntityAsync(entity.BusinessType).GetAwaiter().GetResult();
            string taskRecordNo = Guid.NewGuid().ToString();

            TaskRecordEntity fmisTaskRecordEntity = new TaskRecordEntity()
            {
                WorkflowActivityInstanceId = entity.WorkflowActivityInstanceId,
                TaskRecordNo = taskRecordNo,
                TaskCategory = OATaskCategoryType.Finance,
                BusinessTypeName = dictionaryReferenceEntity.ItemValue,
                BusinessType = entity.BusinessType,
                RelevantTaskRecordNo = entity.RelevantTaskRecordNo,
                CurrentlyStep = entity.CurrentlyStep,
                //TaskType = entity.TaskType,
                TaskRemark = entity.TaskRemark,
                //TaskTypeName = entity.TaskType.GetDescriptionString(),
                //ReceivableAmount = entity.ReceivableAmount,
                //PayableAmount = entity.PayableAmount,
                //ActualReceiptAmount = entity.ActualReceiptAmount,
                //ActualPaidAmount = entity.ActualPaidAmount,
                //SaleUniqueCode = entity.SaleUniqueCode,
                //SaleContractNo = entity.SaleContractNo,
                //PurchaseContractNo = entity.PurchaseContractNo,
                //PurchaseUniqueCode = entity.PurchaseUniqueCode,
                //CapitalPoolWithdrawId = entity.CapitalPoolWithdrawId
            };
            //if (isAppend)
            //{
            //    this.taskRecordData.InsertAsync(taskRecordEntity);
            //}
            //else
            //{
            //    this.taskRecordData.InsertAsync(taskRecordEntity);
            //}
        }
        #endregion

        #region 获取指定的任务单记录信息
        /// <summary>
        /// 获取指定的任务单记录信息
        /// </summary>
        /// <param name="applyRecordCode">申请编号</param>
        /// <returns></returns>
        public TaskRecordViewDto GetTaskRecordInfo(string applyRecordCode)
        {
            var workflowActivityInstanceReferenceEntity = this.workflowActivityInstanceReferenceData.Get(applyRecordCode).GetAwaiter().GetResult(); ;
            if (workflowActivityInstanceReferenceEntity != null)
            {
                var task = this.taskRecordData.Get(workflowActivityInstanceReferenceEntity.WorkflowActivityInstanceId).GetAwaiter().GetResult().First();

                if (task == null)
                    return new TaskRecordViewDto();
                TaskRecordViewDto viewDto = task.As<TaskRecordViewDto>();
                var workflowActivityInstanceDto = this.workflowActivityInstanceBusinessData.GetEntity(task.WorkflowActivityInstanceId).GetAwaiter().GetResult().As<WorkflowActivityInstanceDto>();
                WorkflowActivityInstanceRecordDto workflowActivityInstanceRecordDto = workflowActivityInstanceDto.As<WorkflowActivityInstanceRecordDto>();
                workflowActivityInstanceRecordDto.TaskRecords = this.GetTaskRecords(task.WorkflowActivityInstanceId).ToList();
                workflowActivityInstanceRecordDto.TaskRejectRecords = this.GetTaskRejectRecords(task.WorkflowActivityInstanceId).ToList();
                workflowActivityInstanceRecordDto.TaskResourceRecords = this.taskResourceRecordService.GetList(task.WorkflowActivityInstanceId).ToList();
                viewDto.WorkflowActivityInstanceRecord = workflowActivityInstanceRecordDto;
                viewDto.TaskReceiverRecordDtos = this.taskReceiverRecordData.GetByWorkflowActivityInstanceId(task.WorkflowActivityInstanceId).GetAwaiter().GetResult().As<List<TaskReceiverRecordDto>>();
                viewDto.StepInstanceList = this.workflowActivityInstanceBusinessData.GetSteps(task.WorkflowActivityInstanceId).GetAwaiter().GetResult().As<List<WorkflowActivityStepInstanceDto>>();
                return viewDto;
            }
            return null;
        }
        #endregion

        #region 处理有被驳回的任务为完成,只更新任务状态
        public bool HandleHasRejectedRecordByTaskRecordNo(string taskRecordNo)
        {
            return this.taskRecordData.UpdateHandleStatus(taskRecordNo, OATaskHandleStatus.Handled).GetAwaiter().GetResult();
        }
        #endregion

        public TaskRecordViewDto GetTaskRecordInfoByActivityInstanceId(long workflowActivityInstanceId)
        {
            var task = this.taskRecordData.Get(workflowActivityInstanceId).GetAwaiter().GetResult().First();

            if (task == null)
                return new TaskRecordViewDto();
            TaskRecordViewDto viewDto = task.As<TaskRecordViewDto>();
            var workflowActivityInstanceDto = this.workflowActivityInstanceBusinessData.GetEntity(task.WorkflowActivityInstanceId).GetAwaiter().GetResult().As<WorkflowActivityInstanceDto>();
            WorkflowActivityInstanceRecordDto workflowActivityInstanceRecordDto = workflowActivityInstanceDto.As<WorkflowActivityInstanceRecordDto>();
            workflowActivityInstanceRecordDto.TaskRecords = this.GetTaskRecords(task.WorkflowActivityInstanceId).ToList();
            workflowActivityInstanceRecordDto.TaskRejectRecords = this.GetTaskRejectRecords(task.WorkflowActivityInstanceId).ToList();
            workflowActivityInstanceRecordDto.TaskResourceRecords = this.taskResourceRecordService.GetList(task.WorkflowActivityInstanceId).ToList();
            viewDto.WorkflowActivityInstanceRecord = workflowActivityInstanceRecordDto;
            viewDto.StepInstanceList = this.workflowActivityInstanceBusinessData.GetSteps(task.WorkflowActivityInstanceId).GetAwaiter().GetResult().As<List<WorkflowActivityStepInstanceDto>>();
            return viewDto;
        }

        #region 关闭工作流
        public TaskRecordDto UpdateTaskRecordStatusClose(string taskRecordNo)
        {
            var taskRecordEntity = this.taskRecordData.GetEntity(taskRecordNo).GetAwaiter().GetResult();
            if (taskRecordEntity == null)
            {
                throw new ArgumentException("工作流记录不存在");
            }
            this.taskRecordData.UpdateHandleStatus(taskRecordNo, OATaskHandleStatus.Closed).GetAwaiter().GetResult();
            this.workflowActivityInstanceBusinessData.UpdateActivityStatus(taskRecordEntity.WorkflowActivityInstanceId, ActivityInstanceStatus.Done).GetAwaiter().GetResult();
            return this.taskRecordData.GetEntity(taskRecordNo).GetAwaiter().GetResult().As<TaskRecordDto>();
        }
        #endregion

        public PageableList<TaskRecordDto> GetPageableList(string taskRecordNo, int? companyId, long? adminId, string[] workflowKeys, long? workflowActivityInstanceId, string referenceNumber, bool? isMyApproved, DateTime? startDate, DateTime? endDate, OATaskHandleStatus? status, string sortName, bool? ascending, int pageIndex, int pageSize)
        {
            // 如果不是超级管理员，则 AdminId 必须是自己。
            if (!applicationContextService.Admin.IsSystemAccount)
            {
                adminId = applicationContextService.Admin.AdminId;
            }

            var (list, count) = this.taskRecordData.GetPageableListAsync(taskRecordNo, companyId, adminId, workflowKeys, workflowActivityInstanceId, referenceNumber, isMyApproved, startDate, endDate, status, sortName, ascending, pageIndex, pageSize).GetAwaiter().GetResult();

            return new PageableList<TaskRecordDto>()
            {
                Items = list.TransformTo<TaskRecordDto>(onAfter: (_, dest) =>
                {
                    var relatedTaskRecords = taskRecordData.GetByWorkflowActivityInstanceIdAsync(dest.WorkflowActivityInstanceId).GetAwaiter().GetResult();

                    if (relatedTaskRecords.Any())
                    {
                        var names = relatedTaskRecords.Where(p => p.CurrentlyStep > 0).OrderBy(p => p.CurrentlyStep).Select(p => p.TaskExecuterFullName).Distinct();
                        dest.Approvers = string.Join(",", names);
                    }
                    else
                    {
                        dest.Approvers = dest.TaskExecuterFullName;
                    }

                    var firstTaskRecord = relatedTaskRecords.First(p => p.CurrentlyStep == 0);

                    if (firstTaskRecord != null)
                    {
                        dest.Applicant = firstTaskRecord.TaskExecuterFullName;
                    }
                }),
                Count = count,
                PageIndex = pageIndex,
                PageSize = pageSize
            };
        }

        public TaskRecordViewDto GetTask(string taskRecordNo)
        {
            var taskRecord = this.taskRecordData.GetEntity(taskRecordNo).GetAwaiter().GetResult();

            if (taskRecord == null)
            {
                throw new ObjectNotFoundException();
            }

            var relatedTaskRecords = taskRecordData.GetByWorkflowActivityInstanceIdAsync(taskRecord.WorkflowActivityInstanceId).GetAwaiter().GetResult();
            var workflowActivityInstance = this.workflowActivityInstanceBusinessData.GetEntity(taskRecord.WorkflowActivityInstanceId).GetAwaiter().GetResult();

            return this.GetTaskRecordView(taskRecord, relatedTaskRecords, workflowActivityInstance);
        }

        private TaskRecordViewDto GetTaskRecordView(TaskRecordEntity taskRecord, IEnumerable<TaskRecordEntity> relatedTaskRecords, WorkflowActivityInstanceEntity workflowActivityInstance)
        {
            return taskRecord.TransformTo<TaskRecordViewDto>(onAfter: (_, taskRecordDto) =>
            {
                if (relatedTaskRecords.Any())
                {
                    taskRecordDto.Approvers = string.Join(",", relatedTaskRecords.Where(p => p.CurrentlyStep > 0).OrderBy(p => p.CurrentlyStep).Select(p => p.TaskExecuterFullName).Distinct());
                }
                else
                {
                    taskRecordDto.Approvers = taskRecord.TaskExecuterFullName;
                }

                var firstTaskRecord = relatedTaskRecords.FirstOrDefault(p => p.CurrentlyStep == 0);

                if (firstTaskRecord != null)
                {
                    taskRecordDto.Applicant = firstTaskRecord.TaskExecuterFullName;
                }

                taskRecordDto.WorkflowActivityInstanceRecord = workflowActivityInstance.TransformTo<WorkflowActivityInstanceRecordDto>(onAfter: (__, workflowActivityInstanceRecordDto) =>
                {
                    workflowActivityInstanceRecordDto.TaskRecords = relatedTaskRecords.TransformTo<TaskRecordDto>();
                    workflowActivityInstanceRecordDto.TaskRejectRecords = this.GetTaskRejectRecords(taskRecord.WorkflowActivityInstanceId);
                    workflowActivityInstanceRecordDto.TaskResourceRecords = this.taskResourceRecordService.GetList(taskRecord.WorkflowActivityInstanceId);
                });

                taskRecordDto.StepInstanceList = this.workflowActivityInstanceBusinessData.GetSteps(taskRecord.WorkflowActivityInstanceId).GetAwaiter().GetResult().TransformTo<WorkflowActivityStepInstanceDto>();
            });
        }

        public IEnumerable<TaskRecordViewDto> GetTasksByReferenceNumber(string referenceNumber)
        {
            var list = new List<TaskRecordViewDto>();

            foreach (var reference in this.workflowActivityInstanceReferenceData.GetWorkflowActivityInstanceReferencesByReferenceNumber(referenceNumber).GetAwaiter().GetResult())
            {
                var workflowActivityInstance = this.workflowActivityInstanceBusinessData.GetEntity(reference.WorkflowActivityInstanceId).GetAwaiter().GetResult();
                var relatedTaskRecords = taskRecordData.GetByWorkflowActivityInstanceIdAsync(reference.WorkflowActivityInstanceId).GetAwaiter().GetResult();

                var currentTaskRecord = relatedTaskRecords.FirstOrDefault(p => p.CurrentlyStep == workflowActivityInstance.CurrentlyStep);

                list.Add(this.GetTaskRecordView(currentTaskRecord, relatedTaskRecords, workflowActivityInstance));
            }

            return list.OrderBy(p => p.WorkflowActivityInstanceId);
        }

        //public TaskRecordViewDto Approve(string taskRecordNo, GeneralRequestDto requestDto)
        //{
        //    var taskRecord = this.taskRecordData.GetEntity(taskRecordNo).GetAwaiter().GetResult();

        //    if (taskRecord == null)
        //    {
        //        throw new ObjectNotFoundException();
        //    }

        //    this.generalWorkflowService.Approve(taskRecord.WorkflowActivityInstanceId, taskRecord.CurrentlyStep.Value, requestDto.Remark, requestDto.Parameters);

        //    return this.GetTask(taskRecordNo);
        //}

        //public TaskRecordViewDto Reject(string taskRecordNo, GeneralRequestDto requestDto)
        //{
        //    var taskRecord = this.taskRecordData.GetEntity(taskRecordNo).GetAwaiter().GetResult();

        //    if (taskRecord == null)
        //    {
        //        throw new ObjectNotFoundException();
        //    }

        //    this.generalWorkflowService.Reject(taskRecord.WorkflowActivityInstanceId, taskRecord.CurrentlyStep.Value, requestDto.Remark, requestDto.Parameters);

        //    return this.GetTask(taskRecordNo);
        //}

        //public TaskRecordViewDto Pause(string taskRecordNo, GeneralRequestDto requestDto)
        //{
        //    var taskRecord = this.taskRecordData.GetEntity(taskRecordNo).GetAwaiter().GetResult();

        //    if (taskRecord == null)
        //    {
        //        throw new ObjectNotFoundException();
        //    }

        //    this.generalWorkflowService.Pause(taskRecord.WorkflowActivityInstanceId, requestDto.Remark, requestDto.Parameters);

        //    return this.GetTask(taskRecordNo);
        //}

        //public TaskRecordViewDto Close(string taskRecordNo, GeneralRequestDto requestDto)
        //{
        //    var taskRecord = this.taskRecordData.GetEntity(taskRecordNo).GetAwaiter().GetResult();

        //    if (taskRecord == null)
        //    {
        //        throw new ObjectNotFoundException();
        //    }

        //    this.generalWorkflowService.Close(taskRecord.WorkflowActivityInstanceId, requestDto.Remark, requestDto.Parameters);

        //    return this.GetTask(taskRecordNo);
        //}

        public IEnumerable<TaskReplyRecordDto> GetTaskReplies(string taskRecordNo)
        {
            var taskRecord = this.taskRecordData.GetEntity(taskRecordNo).GetAwaiter().GetResult();

            if (taskRecord == null)
            {
                throw new ObjectNotFoundException();
            }

            var taskRejectRecord = this.taskRejectRecordData.GetByWorkflowActivityInstanceId(taskRecord.WorkflowActivityInstanceId, taskRecordNo).GetAwaiter().GetResult();

            if (taskRejectRecord == null)
            {
                return new List<TaskReplyRecordDto>();
            }

            var list = this.taskRejectReplyRecordData.GetEntities(taskRejectRecord.WorkflowActivityInstanceId, taskRejectRecord.TaskRejectRecordId).GetAwaiter().GetResult();

            return list.Select(p => new TaskReplyRecordDto
            {
                TaskReplyRecordId = p.TaskRejectReplyRecordId,
                WorkflowActivityInstanceId = p.WorkflowActivityInstanceId,
                TaskRecordNo = taskRecordNo,
                Content = p.ReplyContent,
                UserId = p.ReplyAdminId,
                FullName = p.ReplyFullName,
                RoleType = RoleType.Admin,
                CreateTime = p.ReplyTime
            });
        }

        public TaskReplyRecordDto CreateTaskReply(string taskRecordNo, TaskReplyRecordRequestDto requestDto)
        {
            var taskRecord = this.taskRecordData.GetEntity(taskRecordNo).GetAwaiter().GetResult();

            if (taskRecord == null)
            {
                throw new ObjectNotFoundException();
            }

            var taskRejectRecord = this.taskRejectRecordData.GetByWorkflowActivityInstanceId(taskRecord.WorkflowActivityInstanceId, taskRecordNo).GetAwaiter().GetResult();

            if (taskRejectRecord == null)
            {
                throw new NotImplementedException("当前仅允许对被驳回的工作流任务添加回复。");
            }

            var entity = this.taskRejectReplyRecordData.Add(new TaskRejectReplyRecordEntity
            {
                WorkflowActivityInstanceId = taskRecord.WorkflowActivityInstanceId,
                TaskRejectRecordId = taskRejectRecord.TaskRejectRecordId,
                ReplyContent = requestDto.Content,
                ReplyAdminId = applicationContextService.Admin.AdminId,
                ReplyFullName = applicationContextService.Admin.FullName,
                ReplyTime = DateTime.Now
            }).GetAwaiter().GetResult();

            return new TaskReplyRecordDto
            {
                TaskReplyRecordId = entity.TaskRejectReplyRecordId,
                WorkflowActivityInstanceId = entity.WorkflowActivityInstanceId,
                TaskRecordNo = taskRecordNo,
                Content = entity.ReplyContent,
                UserId = entity.ReplyAdminId,
                FullName = entity.ReplyFullName,
                RoleType = RoleType.Admin,
                CreateTime = entity.ReplyTime
            };
        }

        public IEnumerable<TaskRecordGroupWorkflowTypeDto> GetPendingTaskList(long adminId, RoleType roleType)
        {
            return this.taskRecordData.GetPendingTaskListAsync(adminId, roleType).GetAwaiter().GetResult().As<IEnumerable<TaskRecordGroupWorkflowTypeDto>>();
        }

        public IEnumerable<TaskRecordGroupWorkflowTypeDto> GetAppliedTaskList(long adminId, RoleType roleType)
        {
            return this.taskRecordData.GetAppliedTaskListAsync(adminId, roleType).GetAwaiter().GetResult().As<IEnumerable<TaskRecordGroupWorkflowTypeDto>>();
        }

        public PageableList<TaskRecordProgressDto> GetTaskProgressList(long? adminId, RoleType? roleType, DateTime? startDate, DateTime? endDate, OATaskHandleStatus? handleStatus, string sortName, bool? ascending, int pageIndex, int pageSize)
        {
            var (list, count) = this.taskRecordData.GetTaskRecordListAsync(null, null, startDate, endDate, handleStatus, sortName, ascending, pageIndex, pageSize).GetAwaiter().GetResult();

            return new PageableList<TaskRecordProgressDto>()
            {
                Items = list.TransformTo<TaskRecordProgressDto>(onAfter: (_, dest) =>
                {
                    var relatedTaskRecords = taskRecordData.GetByWorkflowActivityInstanceIdAsync(dest.WorkflowActivityInstanceId).GetAwaiter().GetResult();

                    if (relatedTaskRecords.Any())
                    {
                        var names = relatedTaskRecords.Where(p => p.CurrentlyStep > 0).OrderBy(p => p.CurrentlyStep).Select(p => p.TaskExecuterFullName).Distinct();
                        dest.Approvers = string.Join(",", names);
                    }
                    else
                    {
                        dest.Approvers = dest.TaskExecuterFullName;
                    }

                    var firstTaskRecord = relatedTaskRecords.First(p => p.CurrentlyStep == 0);

                    if (firstTaskRecord != null)
                    {
                        dest.Applicant = firstTaskRecord.TaskExecuterFullName;
                    }
                }),
                Count = count,
                PageIndex = pageIndex,
                PageSize = pageSize
            };
        }

        public void UpdateRollBack(long workflowActivityInstanceId)
        {
            var taskRecordList = this.taskRecordData.GetByWorkflowActivityInstanceIdAsync(workflowActivityInstanceId).GetAwaiter().GetResult();
            if (taskRecordList.Any() && !taskRecordList.OrderByDescending(p => p.CreateTime).First().TaskExecuterAdminId.HasValue && taskRecordList.Count() > 2)
            {
                taskRecordList = taskRecordList.OrderByDescending(p => p.CreateTime);
                //删除最后一条记录，更新倒数第二条为Pending，更新步骤为前一步的步骤
                this.taskRecordData.UpdateRollBack(taskRecordList.First().TaskRecordNo, taskRecordList.Skip(1).First().TaskRecordNo, taskRecordList.Skip(1).First().CurrentlyStep.Value, workflowActivityInstanceId).GetAwaiter().GetResult();
            }
        }

        public bool UpdateCloseWorkflowTask(string taskRecordNo, RemarkRequestDto requestDto)
        {
            var taskRecord = this.taskRecordData.GetEntity(taskRecordNo).Result;
            if (taskRecord == null)
            {
                throw new ArgumentException("任务记录不存在");
            }
            if (taskRecord.HandleStatus == OATaskHandleStatus.Closed)
            {
                throw new ArgumentException("此任务已关闭");
            }
            //var fmisTaskRecord = this.taskRecordData.GetLatestRecord(taskRecord.WorkflowActivityInstanceId).Result;
            databaseContext.BeginTransaction();
            //if (fmisTaskRecord != null)
            //{
            //    if (taskRecord.BusinessType == OATaskBusinessType.WorkflowBusiness_DepositPayment_Purchase.ToString())
            //    {
            //        this.vehiclePurchaseContractData.UpdateVehiclePurchaseContractStatusAsync(fmisTaskRecord.PurchaseContractNo, VehiclePurchaseContractStatus.DepositPendingPayment).GetAwaiter().GetResult();
            //    }
            //    else if (taskRecord.BusinessType == OATaskBusinessType.WorkflowBusiness_SingleLastPayment_Purchase.ToString())
            //    {
            //        this.vehiclePurchaseCheckListData.UpdateVehiclePurchaseContractStatusAsync(fmisTaskRecord.PurchaseUniqueCode, VehiclePurchaseContractStatus.LastPendingPayment).GetAwaiter().GetResult();
            //    }
            //    else if (taskRecord.BusinessType == OATaskBusinessType.WorkflowBusiness_LastPayment_Purchase.ToString())
            //    {
            //        this.vehiclePurchaseContractData.UpdateVehiclePurchaseContractStatusAsync(fmisTaskRecord.PurchaseContractNo, VehiclePurchaseContractStatus.LastPendingPayment).GetAwaiter().GetResult();
            //    }
            //}
            this.taskRecordData.UpdateHandleStatus(taskRecordNo, OATaskHandleStatus.Closed).GetAwaiter().GetResult();
            //更新工作流任务关闭
            this.workflowActivityInstanceBusinessData.UpdateActivityStatus(taskRecord.WorkflowActivityInstanceId, ActivityInstanceStatus.Closed).GetAwaiter().GetResult();
            databaseContext.Commit();
            return true;

        }
    }
}
